【Clojureでゼロから作るDeep Learning】 1章 Python入門
1.1 Pythonとは
1.2 Pythonのインストール
1.2.1 Pythonのバージョン
2020年3月時点の最新版を利用する。
Clojure 1.10.1
Python 3.8
1.2.2 使用する外部ライブラリ
【Clojure】
code:bash
$ lein new deep-learning-from-scratch
code:clojure
(defproject deep-learning-from-scratch "0.1.0-SNAPSHOT"
:description "FIXME: write description"
:license {:name "EPL-2.0 OR GPL-2.0-or-later WITH Classpath-exception-2.0"
:profiles
code:dev/src/user.clj
(ns user
(defn refresh options
(stest/instrument)
result))
【Python】
code:bash
$ cd deep-learing-from-scratch/
$ pipenv install numpy matplotlib
$ pipenv install -d ipython
code:Pipfile
source
name = "pypi"
verify_ssl = true
ipython = "*"
numpy = "*"
matplotlib = "*"
python_version = "3.8"
1.2.3 Anacondaディストリビューション
1.3 Pythonインタプリタ
【Python】
code:bash
$ pipenv shell
$ python --version
Python 3.8.2
$ ipython
Python 3.8.2 (default, Mar 28 2020, 23:36:11)
Type 'copyright', 'credits' or 'license' for more information
IPython 7.13.0 -- An enhanced Interactive Python. Type '?' for help.
code:python
【Clojure】
code:bash
$ lein repl
OpenJDK 64-Bit Server VM warning: Options -Xverify:none and -noverify were deprecated in JDK 13 and will likely be removed in a future release.
nREPL server started on port 64301 on host 127.0.0.1 - nrepl://127.0.0.1:64301
REPL-y 0.4.4, nREPL 0.6.0
Clojure 1.10.1
OpenJDK 64-Bit Server VM 14+36-1461
Docs: (doc function-name-here)
(find-doc "part-of-name-here")
Source: (source function-name-here)
Javadoc: (javadoc java-object-or-class-here)
Exit: Control+D or (exit) or (quit)
Results: Stored in vars *1, *2, *3, an exception in *e
user=>
code:clojure
user=> (+ 1 2)
3
1.3.1 算術計算
Clojureで整数同士の除算 / は割り切れない場合に有理数 clojure.lang.Ratio になる。
code:clojure
user> (- 1 2)
-1
user> (* 4 5)
20
user> (/ 7 5)
7/5
user> (/ 7.0 5)
1.4
user> (/ 7 5.0)
1.4
user> (double (/ 7 5))
1.4
user> (Math/pow 3 2)
9.0
1.3.2 データ型
code:clojure
user> (type 10)
java.lang.Long
user> (type 2.718)
java.lang.Double
user> (type "hello")
java.lang.String
1.3.3 変数
原則として特殊形式 let によるローカル束縛を利用する。
再代入が必要な場合には atom(もしくは volatile!)の利用も検討する。
トップレベルの定義には def マクロ。
code:clojure
(println x))
10
nil
(println x))
100
nil
user> (let [x 100
y 3.14]
(* x y))
314.0
user> (let [x 100
y 3.14]
(type (* x y)))
java.lang.Double
1.3.4 リスト
Clojureではベクター(vector; clojure.lang.IPersistentVector)またはシーケンス(sequence; clojure.lang.ISeq)など。
破壊的な操作が必要な場合にはJava配列(array)の利用も検討する。
code:clojure
(println a))
nil
(count a))
5
(nth a 0))
1
(nth a 4))
5
a' (assoc a 4 99)]
(println a'))
nil
a' (assoc a 4 99)]
(subvec a' 0 2))
a' (assoc a 4 99)]
(subvec a' 1))
a' (assoc a 4 99)]
(vec (take 3 a')))
a' (assoc a 4 99)]
(vec (drop-last 1 a')))
a' (assoc a 4 99)]
(vec (drop-last 2 a')))
1.3.5 ディクショナリ
Clojureではマップ(map; clojure.lang.IPersistentMap)。
キーには通常、キーワード(keyword)を利用する。
code:clojure
(:height me))
100
user> (let [me {:height 100}
me' (assoc me :weight 70)]
(println me'))
{:height 100, :weight 70}
nil
1.3.6 ブーリアン
code:clojure
user> (let [hungry? true
sleepy? false]
(type hungry?))
java.lang.Boolean
user> (let [hungry? true
sleepy? false]
(not hungry?))
false
user> (let [hungry? true
sleepy? false]
(and hungry? sleepy?))
false
user> (let [hungry? true
sleepy? false]
(or hungry? sleepy?))
true
1.3.7 if文
Clojureでは if 特殊形式、when マクロ、 cond マクロなど。
code:clojure
(when hungry?
(println "I'm hungry")))
I'm hungry
nil
(if hungry?
(println "I'm hungry")
(do (println "I'm not hungry")
(println "I'm sleepy"))))
I'm not hungry
I'm sleepy
nil
1.3.8 for文
Clojureでは doseq マクロなど。
code:clojure
(println i))
1
2
3
nil
1.3.9 関数
Clojureでは defn マクロなど。
文字列連結は str 関数。
code:clojure
user> (defn hello []
(println "Hello World!"))
user> (hello)
Hello World!
nil
(println (str "Hello " object "!")))
user> (hello "cat")
Hello cat!
nil
1.4 Pythonスクリプトファイル
1.4.1 ファイルに保存
code:src/deep_learning_from_scratch/ch01/hungry.clj
(ns deep-learning-from-scratch.ch01.hungry)
(defn -main []
(println "I'm hungry!"))
code:bash
$ lein run -m deep-learning-from-scratch.ch01.hungry
I'm hungry!
lein run でのスクリプト実行はLeiningenの起動まで時間が掛かるため、REPLから実行したほうが素早く試せる。
code:clojure
user> (refresh)
:reloading (deep-learning-from-scratch.core deep-learning-from-scratch.core-test user deep-learning-from-scratch.ch01.hungry)
:ok
user> (deep-learning-from-scratch.ch01.hungry/-main)
I'm hungry!
nil
1.4.2 クラス
Clojureはオブジェクト指向言語ではないためクラスを定義することは稀だが、同等の処理は異なる方法で実現できる。
code:src/deep_learning_from_scratch/ch01/man.clj
(ns deep-learning-from-scratch.ch01.man
(s/def ::name string?)
(s/def ::man (s/keys :req ::name)) (s/fdef hello
:args (s/cat :man ::man))
(println (str "Hello " (::name man) "!")))
(s/fdef goodbye
:args (s/cat :man ::man))
(println (str "Good-bye " (::name man) "!")))
code:clojure
user> (refresh)
:reloading (deep-learning-from-scratch.ch01.man)
:ok
nil
(man/hello m))
Hello David!
nil
(man/goodbye m))
Good-bye David!
nil
1.5 NumPy
1.5.1 NumPyのインポート
+, -, *, / などの記号演算子は clojure.core.matrix.operators に含まれているので適宜利用する。
code:clojure
nil
user> (m/set-current-implementation :clatrix)
:clatrix
1.5.2 NumPy配列の生成
code:clojure
(1.0 2.0 3.0)
(println x))
(1.0 2.0 3.0)
nil
(type x))
clatrix.core.Vector
1.5.3 NumPyの算術計算
code:clojure
(m/add x y))
(3.0 6.0 9.0)
(m/sub x y))
(-1.0 -2.0 -3.0)
(m/mul x y))
(2.0 8.0 18.0)
(m/div x y))
(0.5 0.5 0.5)
(m/div x 2))
(0.5 1.0 1.5)
1.5.4 NumPyのN次元配列
code:clojure
user> (m/array 1 2] [3 4)
A 2x2 matrix
-------------
1.00e+00 2.00e+00
3.00e+00 4.00e+00
user> (let [A (m/array 1 2] [3 4)]
(println A))
A 2x2 matrix
-------------
1.00e+00 2.00e+00
3.00e+00 4.00e+00
nil
user> (let [A (m/array 1 2] [3 4)]
(m/shape A))
user> (let [A (m/array 1 2] [3 4)]
(m/element-type A))
double
user> (let [A (m/array 1 2] [3 4)
B (m/array 3 0] [0 6)]
(m/add A B))
A 2x2 matrix
-------------
4.00e+00 2.00e+00
3.00e+00 1.00e+01
user> (let [A (m/array 1 2] [3 4)
B (m/array 3 0] [0 6)]
(m/mul A B))
A 2x2 matrix
-------------
3.00e+00 0.00e+00
0.00e+00 2.40e+01
user> (let [A (m/array 1 2] [3 4)]
(m/mul A 10))
A 2x2 matrix
-------------
1.00e+01 2.00e+01
3.00e+01 4.00e+01
1.5.5 ブロードキャスト
code:clojure
user> (let [A (m/array 1 2] [3 4)
(m/mul A B))
A 2x2 matrix
-------------
1.00e+01 4.00e+01
3.00e+01 8.00e+01
1.5.6 要素へのアクセス
code:clojure
user> (let [X (m/array 51 55] 14 19 [0 4)] (println X))
A 3x2 matrix
-------------
5.10e+01 5.50e+01
1.40e+01 1.90e+01
0.00e+00 4.00e+00
nil
user> (let [X (m/array 51 55] 14 19 [0 4)] (m/slice X 0))
(51.0 55.0)
user> (let [X (m/array 51 55] 14 19 [0 4)] (m/mget X 0 1))
55.0
user> (let [X (m/array 51 55] 14 19 [0 4)] (println row)))
A 1x2 matrix
-------------
5.10e+01 5.50e+01
A 1x2 matrix
-------------
1.40e+01 1.90e+01
A 1x2 matrix
-------------
0.00e+00 4.00e+00
nil
user> (let [X (m/array 51 55] 14 19 [0 4) X' (->> X m/eseq m/array)]
(println X'))
(51.0 55.0 14.0 19.0 0.0 4.0)
nil
user> (let [X (m/array 51 55] 14 19 [0 4) X' (->> X m/eseq m/array)]
(m/select-indices X' 0 2 4)) (51.0 14.0 0.0)
user> (let [X (m/array 51 55] 14 19 [0 4) X' (->> X m/eseq m/array)]
(->> X' (filter #(> % 15)) m/array)) (51.0 55.0 19.0)
1.6 Matplotlib
1.6.1 単純なグラフの描画
code:clojure:src/deep_learning_from_scratch/ch01/sin_graph.clj
(ns deep-learning-from-scratch.ch01.sin-graph
(defn -main []
(m/set-current-implementation :clatrix)
(let [x (m/array (range 0 6 0.1))
y (m/sin x)]
(doto (charts/xy-plot x y)
incanter/view)))
code:clojure
user> (refresh)
:reloading (deep-learning-from-scratch.ch01.sin-graph)
:ok
user> (deep-learning-from-scratch.ch01.sin-graph/-main)
https://gyazo.com/8314612d928cb27db4ed3e77a206702a
1.6.2 pyplotの機能
code:clojure:src/deep_learning_from_scratch/ch01/sin_cos_graph.clj
(ns deep-learning-from-scratch.ch01.sin-cos-graph
(defn -main []
(m/set-current-implementation :clatrix)
(let [x (m/array (range 0 6 0.1))
y1 (m/sin x)
y2 (m/cos x)]
(doto (charts/xy-plot x y1
:series-label "sin"
:x-label "x"
:y-label "y"
:title "sin & cos"
:legend true)
(charts/add-lines x y2
:series-label "cos")
(charts/set-stroke :dataset 1
:dash 5)
incanter/view)))
code:clojure
user> (refresh)
:reloading (deep-learning-from-scratch.ch01.sin-cos-graph)
:ok
user> (deep-learning-from-scratch.ch01.sin-cos-graph/-main)
https://gyazo.com/91faeed00c163073b6c99cb6c54a3af5
1.6.3 画像の表示
1.7 まとめ